import json
import os
import re

def generate_medical_kg_result(json_str, output_prefix="report", person_name="未知患者"):
    # 读取你提供的完整 HTML 模板（作为多行字符串）
    html_template = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>医学死亡因果链知识图谱</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        .node {
            cursor: pointer;
            stroke: #fff;
            stroke-width: 2px;
        }

        .link {
            stroke: #999;
            stroke-opacity: 0.8;
            stroke-width: 2px;
            fill: none;
            marker-end: url(#arrowhead);
        }

        .link-label {
            font-size: 11px;
            fill: #333;
            text-anchor: middle;
            pointer-events: none;
            font-weight: bold;
        }

        .node-label {
            font-size: 10px;
            text-anchor: middle;
            pointer-events: none;
            fill: #333;
            font-weight: bold;
        }

        .tooltip {
            position: absolute;
            padding: 12px;
            background: rgba(0, 0, 0, 0.9);
            color: white;
            border-radius: 8px;
            pointer-events: none;
            font-size: 12px;
            z-index: 1000;
            max-width: 300px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }

        .legend-item {
            display: flex;
            align-items: center;
            margin: 4px 0;
        }

        .legend-color {
            width: 18px;
            height: 18px;
            border-radius: 50%;
            margin-right: 8px;
        }

        .sequence-badge {
            font-size: 10px;
            font-weight: bold;
            fill: white;
            text-anchor: middle;
            pointer-events: none;
        }
        .main-chain1{
            display: flex;
            flex-direction: column-reverse;
        }
    </style>
</head>
<body class="bg-gray-100 p-4">
    <div class="max-w-7xl mx-auto">
        <h1 class="text-3xl font-bold text-center mb-6 text-gray-800">医学死亡因果链知识图谱</h1>

        <div class="bg-white rounded-lg shadow-lg p-6 mb-6">
            <h2 class="text-xl font-semibold mb-4">患者：{{PERSON_NAME}}</h2>

            <div class="grid grid-cols-1 lg:grid-cols-5 gap-4 mb-6">
                <!-- 图例 -->
                <div class="bg-gray-50 p-4 rounded-lg">
                    <h3 class="font-semibold mb-3 text-sm">疾病角色图例</h3>
                    <div class="space-y-2">
                        <div class="legend-item">
                            <div class="legend-color bg-red-600"></div>
                            <span class="text-xs">根本死因</span>
                        </div>
                        <div class="legend-item">
                            <div class="legend-color bg-orange-500"></div>
                            <span class="text-xs">直接死因</span>
                        </div>
                        <div class="legend-item">
                            <div class="legend-color bg-yellow-500"></div>
                            <span class="text-xs">促进因素</span>
                        </div>
                    </div>

                    <h4 class="font-semibold mt-4 mb-2 text-sm">关系类型</h4>
                    <div class="space-y-1 text-xs">
                        <div class="flex items-center">
                            <div class="w-4 h-0.5 bg-red-600 mr-2"></div>
                            <span>导致</span>
                        </div>
                        <div class="flex items-center">
                            <div class="w-4 h-0.5 bg-blue-600 mr-2"></div>
                            <span>加重</span>
                        </div>
                        <div class="flex items-center">
                            <div class="w-4 h-0.5 bg-yellow-600 mr-2"></div>
                            <span>诱发</span>
                        </div>
                    </div>
                </div>

                <!-- 主要死亡链条 -->
                <div class="lg:col-span-2 bg-red-50 p-4 rounded-lg border-l-4 border-red-500">
                    <h3 class="font-semibold mb-3 text-sm text-red-700">主要死亡链条</h3>
                    <div class="space-y-2 main-chain1" id="main-chain">
                        <!-- 动态生成 -->
                    </div>
                </div>

                <!-- 促进因素 -->
                <div class="lg:col-span-2 bg-yellow-50 p-4 rounded-lg border-l-4 border-yellow-500">
                    <h3 class="font-semibold mb-3 text-sm text-yellow-700">促进因素</h3>
                    <div class="space-y-2" id="contributing-factors">
                        <!-- 动态生成 -->
                    </div>
                </div>
            </div>

            <!-- 知识图谱 -->
            <div class="bg-white border-2 border-gray-200 rounded-lg">
                <div class="p-3 bg-gray-50 border-b border-gray-200">
                    <h3 class="font-semibold text-gray-700">疾病关系网络图</h3>
                    <p class="text-sm text-gray-600 mt-1">可拖拽节点，悬停查看详细信息</p>
                </div>
                <div id="graph-container" class="w-full h-96"></div>
            </div>
        </div>
    </div>

    <div id="tooltip" class="tooltip" style="display: none;"></div>

    <script>
        // 数据
        const data = {{JSON_DATA}};

        // 生成主要死亡链条
        function generateMainChain() {
            const container = document.getElementById('main-chain');
            const mainChain = data.death_causality_chain
                .filter(item => item.role === '根本死因' || item.role === '直接死因')
                .sort((a, b) => b.sequence - a.sequence);

            mainChain.forEach((item, index) => {
                const div = document.createElement('div');
                div.className = 'flex items-center space-x-2 p-2 bg-white rounded border';
                div.innerHTML = `
                    <span class="flex-shrink-0 w-6 h-6 bg-red-600 text-white rounded-full flex items-center justify-center text-xs font-bold">${item.sequence}</span>
                    <div class="flex-1 min-w-0">
                        <div class="text-sm font-medium truncate">${item.disease_name}</div>
                        <div class="text-xs text-gray-500">${item.icd10_code}</div>
                    </div>
                `;
                container.appendChild(div);

                if (index < mainChain.length - 1) {
                    const arrow = document.createElement('div');
                    arrow.className = 'flex justify-center my-1';
                    arrow.innerHTML = '<div class="text-red-500 text-lg">↑</div>';
                    container.appendChild(arrow);
                }
            });
        }

        // 生成促进因素
        function generateContributingFactors() {
            const container = document.getElementById('contributing-factors');
            const factors = data.death_causality_chain
                .filter(item => item.role === '促进因素')
                .sort((a, b) => a.sequence - b.sequence);

            factors.forEach(item => {
                const div = document.createElement('div');
                div.className = 'flex items-center space-x-2 p-2 bg-white rounded border';
                div.innerHTML = `
                    <span class="flex-shrink-0 w-6 h-6 bg-yellow-600 text-white rounded-full flex items-center justify-center text-xs font-bold">${item.sequence}</span>
                    <div class="flex-1 min-w-0">
                        <div class="text-sm font-medium truncate">${item.disease_name}</div>
                        <div class="text-xs text-gray-500">${item.icd10_code}</div>
                    </div>
                `;
                container.appendChild(div);
            });
        }

        // 创建知识图谱
        function createKnowledgeGraph() {
            const container = d3.select("#graph-container");
            const width = container.node().offsetWidth;
            const height = 400;

            container.selectAll("*").remove();

            const svg = container.append("svg")
                .attr("width", width)
                .attr("height", height);

            svg.append("defs").append("marker")
                .attr("id", "arrowhead")
                .attr("viewBox", "0 -5 10 10")
                .attr("refX", 28)
                .attr("refY", 0)
                .attr("markerWidth", 6)
                .attr("markerHeight", 6)
                .attr("orient", "auto")
                .append("path")
                .attr("d", "M0,-5L10,0L0,5")
                .attr("fill", "#666");

            const simulation = d3.forceSimulation(data.knowledge_graph_nodes)
                .force("link", d3.forceLink(data.knowledge_graph_edges).id(d => d.id).distance(120))
                .force("charge", d3.forceManyBody().strength(-400))
                .force("center", d3.forceCenter(width / 2, height / 2))
                .force("collision", d3.forceCollide().radius(35));

            const link = svg.append("g")
                .selectAll("path")
                .data(data.knowledge_graph_edges)
                .enter().append("path")
                .attr("class", "link")
                .attr("stroke-width", 2)
                .attr("stroke", d => d.relation === "导致" ? "#dc2626" : "#2563eb");

            const linkLabels = svg.append("g")
                .selectAll("text")
                .data(data.knowledge_graph_edges)
                .enter().append("text")
                .attr("class", "link-label")
                .text(d => d.relation);

            const roleMap = {};
            data.death_causality_chain.forEach(item => {
                const node = data.knowledge_graph_nodes.find(n =>
                    n.label.includes(item.disease_name) || item.disease_name.includes(n.label)
                );
                if (node) {
                    roleMap[node.id] = {role: item.role, sequence: item.sequence};
                }
            });

            const nodeGroup = svg.append("g")
                .selectAll("g")
                .data(data.knowledge_graph_nodes)
                .enter().append("g")
                .call(d3.drag()
                    .on("start", dragstarted)
                    .on("drag", dragged)
                    .on("end", dragended));

            const node = nodeGroup.append("circle")
                .attr("class", "node")
                .attr("r", 25)
                .attr("fill", d => {
                    const roleInfo = roleMap[d.id];
                    if (!roleInfo) return "#6b7280";
                    switch(roleInfo.role) {
                        case "根本死因": return "#dc2626";
                        case "直接死因": return "#f97316";
                        case "促进因素": return "#eab308";
                        default: return "#6b7280";
                    }
                });

            const sequenceLabels = nodeGroup.append("text")
                .attr("class", "sequence-badge")
                .text(d => {
                    const roleInfo = roleMap[d.id];
                    return roleInfo ? roleInfo.sequence : "";
                })
                .attr("dy", 4);

            const nodeLabels = svg.append("g")
                .selectAll("text")
                .data(data.knowledge_graph_nodes)
                .enter().append("text")
                .attr("class", "node-label")
                .text(d => {
                    const label = d.label;
                    return label.length > 8 ? label.substring(0, 6) + "..." : label;
                });

            const tooltip = d3.select("#tooltip");

            nodeGroup.on("mouseover", function(event, d) {
                const roleInfo = roleMap[d.id];
                const role = roleInfo ? roleInfo.role : "未分类";
                const sequence = roleInfo ? roleInfo.sequence : "N/A";

                tooltip.style("display", "block")
                    .html(`
                        <strong>${d.label}</strong><br/>
                        <div class="mt-1 text-gray-300">
                        ICD-10: ${d.icd10}<br/>
                        疾病类型: ${d.type}<br/>
                        死因角色: ${role}<br/>
                        序列号: ${sequence}
                        </div>
                    `)
                    .style("left", (event.pageX + 10) + "px")
                    .style("top", (event.pageY - 10) + "px");
            })
            .on("mouseout", function() {
                tooltip.style("display", "none");
            });

            simulation.on("tick", () => {
                link.attr("d", d => {
                    const dx = d.target.x - d.source.x;
                    const dy = d.target.y - d.source.y;
                    const dr = Math.sqrt(dx * dx + dy * dy) * 1.5;
                    return `M${d.source.x},${d.source.y}A${dr},${dr} 0 0,1 ${d.target.x},${d.target.y}`;
                });

                linkLabels
                    .attr("x", d => (d.source.x + d.target.x) / 2)
                    .attr("y", d => (d.source.y + d.target.y) / 2 - 5);

                nodeGroup
                    .attr("transform", d => `translate(${d.x},${d.y})`);

                nodeLabels
                    .attr("x", d => d.x)
                    .attr("y", d => d.y + 40);
            });

            function dragstarted(event, d) {
                if (!event.active) simulation.alphaTarget(0.3).restart();
                d.fx = d.x;
                d.fy = d.y;
            }

            function dragged(event, d) {
                d.fx = event.x;
                d.fy = event.y;
            }

            function dragended(event, d) {
                if (!event.active) simulation.alphaTarget(0);
                d.fx = null;
                d.fy = null;
            }
        }

        generateMainChain();
        generateContributingFactors();
        createKnowledgeGraph();
        window.addEventListener('resize', createKnowledgeGraph);
    </script>
</body>
</html>'''

    # 验证并解析 JSON
    try:
        data_dict = json.loads(json_str)
    except json.JSONDecodeError as e:
        raise ValueError(f"❌ 无效的 JSON 字符串: {e}")

    # 格式化 JSON（确保在 JS 中合法）
    json_js = json.dumps(data_dict, ensure_ascii=False, indent=4)

    # 替换占位符
    html_content = html_template.replace("{{PERSON_NAME}}", person_name).replace("{{JSON_DATA}}", json_js)

    # 写入文件
    output_file = f"{output_prefix}.html"
    with open(output_file, "w", encoding="utf-8") as f:
        f.write(html_content)

    print(f"✅ 医学知识图谱报告已生成: {os.path.abspath(output_file)}")